package com.lmq.interfaces;// interfaces/Games.java
// (c)2021 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// A Game framework using Factory Methods

interface Game { boolean move(); }
interface GameFactory { Game getGame(); }

class Checkers implements Game {
  private int moves = 0;
  private static final int MOVES = 3;
  @Override public boolean move() {
    System.out.println("Checkers move " + moves);
    return ++moves != MOVES;
  }
}

class CheckersFactory implements GameFactory {
  @Override
  public Game getGame() { return new Checkers(); }
}

class Chess implements Game {
  private int moves = 0;
  private static final int MOVES = 4;
  @Override public boolean move() {
    System.out.println("Chess move " + moves);
    return ++moves != MOVES;
  }
}

class ChessFactory implements GameFactory {
  @Override
  public Game getGame() { return new Chess(); }
}

//public class Games2 {
//  public static void playGame2(GameFactory factory) {
//    Game s = factory.getGame();
//    while(s.move())
//      ;
//  }

public class Games {
  public static void playGame(GameFactory factory) {
    Game s = factory.getGame();
    while(s.move())
      ;
  }


  public static void PlayGame(Game game){

    while(game.move());
//    ;

  }
  public static void main(String[] args) {
    playGame(new CheckersFactory());
    playGame(new ChessFactory());
    Checkers checkers = new Checkers();


    PlayGame(checkers);
  }
}
/* Output:
Checkers move 0
Checkers move 1
Checkers move 2
Chess move 0
Chess move 1
Chess move 2
Chess move 3
*/
/**
 * If the Games class represents a complex piece of code,
 * this approach means you can reuse that code with
 * different types of games.
 * You can imagine more elaborate games that
 * can benefit from this pattern
 * In the next chapter, you'll see a more elegant way to
 * implement factories using anonymous inner classes.
 */

/**
 * Summary
 * It is tempting to decide that interfaces are good,
 * and therefore always choose
 * interfaces over concrete classes.
 * Almost anytime you create a class, you
 * can instead create an interface and a factory.
 * Many people have fallen to this temptation, creating interfaces and factories
 * whenever it's possible.The logic seems to be that you might use
 * a different implementation,
 * so always add that abstraction.It has become a kind of premature designe
 * optimization.
 * Any abstraction should be motivated by a real need.
 * Interfaces should be something
 * you refactor to when necessary, ranther than installing
 * the extra level of indirection everywhere, along with extra complexity.
 * That extra complexity is significant, and if you make someone work
 * through that complexity only to realize that you've added interfaces "just in case"
 * and for no compelling reason-well, if I see such
 * a design I begin questioning all the other designs this particular person has done.
 * An appropriate guideline is to prefer classes to interfaces.
 * Start with classes, and if it becomes clear that interfaces
 * are necessary, refactor.
 * Interfaces are good tool,but they can easily be overused.
 */